package com.csx.framework.springboot.sample.boot;

import com.csx.framework.springboot.sample.SpringBootSampleApplication;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;

/**
 * 生效时机:
 *      在Bean的实例化前后 和 属性注入阶段生效 及 初始化前后执行
 * 使用场景:
 *      对实现了某一类接口的bean在各个生命期间进行收集，或者对某个类型的bean进行统一设置值等等
 * @author cuisongxu
 * @date 2024/2/25 周日 14:10
 */

@Component
public class D4InstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {

    public static boolean isPrint = false;
    @Override
    public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {

        if(!isPrint) {
            isPrint = true;
            System.out.println("顺序4 --- D4InstantiationAwareBeanPostProcessor#predictBeanType 在Bean实例化之前生效,可以拿到 BeanClass 和 BeanName");
            System.out.println();
        }

        return SmartInstantiationAwareBeanPostProcessor.super.predictBeanType(beanClass, beanName);
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(SpringBootSampleApplication.class.isAssignableFrom(beanClass)) {
            System.out.println("顺序5 --- D4InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 在Bean实例化之前生效,可以拿到 BeanClass 和 BeanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        if(SpringBootSampleApplication.class.isAssignableFrom(beanClass)) {
            System.out.println("顺序6 --- D4InstantiationAwareBeanPostProcessor#determineCandidateConstructors 在Bean实例化之前,用于确定bean的构造函数,返回该bean的所有构造函数列表,用户可以扩展该点来自定义选择相应的构造器来实例化bean，可以拿到 BeanClass 和 BeanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass, beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(bean instanceof  SpringBootSampleApplication) {
            System.out.println("顺序7 --- D4InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 在Bean实例化之后生效,可以拿到 BeanObject 和 BeanName ");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }


    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        if(bean instanceof  SpringBootSampleApplication) {
            System.out.println("顺序7-2 --- D4InstantiationAwareBeanPostProcessor#getEarlyBeanReference 在Bean实例化之后生效,可以拿到 BeanObject 和 BeanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.getEarlyBeanReference(bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if(bean instanceof  SpringBootSampleApplication) {
            System.out.println("顺序8 --- D4InstantiationAwareBeanPostProcessor#postProcessProperties 在Bean实例化之后，注入属性时生效,可以拿到 PropertyValues 和 BeanObject 和 BeanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
    }


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof  SpringBootSampleApplication) {
            System.out.println("顺序9 --- D4InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization 在Bean实例化之后，初始化之前执行,可以拿到 BeanObject 和 BeanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof  SpringBootSampleApplication) {
            System.out.println("顺序10 --- D4InstantiationAwareBeanPostProcessor#postProcessAfterInitialization 在Bean初始化之后执行, 可以拿到 BeanObject 和 beanName");
            System.out.println();
        }
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}
